2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../jucer_Headers.h"
27 #include "jucer_MainWindow.h"
28 #include "jucer_ComponentLayoutEditor.h"
29 #include "jucer_JucerDocumentHolder.h"
30 #include "jucer_PrefsPanel.h"
31 #include "jucer_TestComponent.h"
32 #include "../model/jucer_ObjectTypes.h"
33 #include "../properties/jucer_FontPropertyComponent.h"
36 static OldSchoolLookAndFeel
* oldLook
= 0;
37 static const int snapSizes
[] = { 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32 };
39 //==============================================================================
40 class MultiDocHolder
: public MultiDocumentPanel
45 setBackgroundColour (Colour (0xffe6f0ff));
48 bool tryToCloseDocument (Component
* component
)
50 JucerDocumentHolder
* const holder
= dynamic_cast <JucerDocumentHolder
*> (component
);
53 || holder
->getDocument() == 0
54 || holder
->getDocument()->saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk
;
58 //==============================================================================
59 MainWindow::MainWindow()
60 : DocumentWindow ("The Jucer",
62 DocumentWindow::allButtons
)
65 oldLook
= new OldSchoolLookAndFeel();
67 setContentOwned (multiDocHolder
= new MultiDocHolder(), false);
69 setApplicationCommandManagerToWatch (commandManager
);
72 setMacMainMenu (this);
77 setResizable (true, false);
79 centreWithSize (700, 600);
81 // restore the last size and position from our settings file..
82 restoreWindowStateFromString (StoredSettings::getInstance()->getProps()
83 .getValue ("lastMainWindowPos"));
85 // Register all the app commands..
87 commandManager
->registerAllCommandsForTarget (JUCEApplication::getInstance());
88 commandManager
->registerAllCommandsForTarget (this);
90 // use a temporary one of these to harvest its commands..
91 JucerDocumentHolder
tempDesignHolder (ObjectTypes::createNewDocument (0));
92 commandManager
->registerAllCommandsForTarget (&tempDesignHolder
);
95 commandManager
->getKeyMappings()->resetToDefaultMappings();
97 XmlElement
* const keys
= StoredSettings::getInstance()->getProps().getXmlValue ("keyMappings");
101 commandManager
->getKeyMappings()->restoreFromXml (*keys
);
105 addKeyListener (commandManager
->getKeyMappings());
107 // don't want the window to take focus when the title-bar is clicked..
108 setWantsKeyboardFocus (false);
111 // scan for fonts before the app gets started rather than glitching later
112 FontPropertyComponent::preloadAllFonts();
116 MainWindow::~MainWindow()
124 removeKeyListener (commandManager
->getKeyMappings());
126 // save the current size and position to our settings file..
127 StoredSettings::getInstance()->getProps()
128 .setValue ("lastMainWindowPos", getWindowStateAsString());
130 clearContentComponent();
132 deleteAndZero (oldLook
);
135 void MainWindow::closeButtonPressed()
137 JUCEApplication::getInstance()->systemRequestedQuit();
140 JucerDocument
* MainWindow::getActiveDocument() const throw()
142 JucerDocumentHolder
* holder
= dynamic_cast <JucerDocumentHolder
*> (multiDocHolder
->getActiveDocument());
147 return holder
->getDocument();
150 bool MainWindow::closeAllDocuments()
152 return multiDocHolder
->closeAllDocuments (true);
155 bool MainWindow::closeDocument (JucerDocumentHolder
* designHolder
)
157 return multiDocHolder
->closeDocument (designHolder
, true);
160 void MainWindow::openDocument (JucerDocument
* const newDoc
)
162 const File
f (newDoc
->getFile());
164 // check it's not already open..
165 if (f
!= File::nonexistent
)
167 for (int i
= multiDocHolder
->getNumDocuments(); --i
>= 0;)
169 JucerDocumentHolder
* holder
= dynamic_cast <JucerDocumentHolder
*> (multiDocHolder
->getDocument (i
));
171 if (holder
!= 0 && holder
->getDocument()->getFile() == f
)
173 multiDocHolder
->setActiveDocument (holder
);
180 multiDocHolder
->addDocument (new JucerDocumentHolder (newDoc
), Colour (0xffc4cdcd), true);
183 bool MainWindow::openFile (const File
& file
)
185 JucerDocument
* newDoc
= ObjectTypes::loadDocumentFromFile (file
, true);
188 openDocument (newDoc
);
193 bool MainWindow::isInterestedInFileDrag (const StringArray
& filenames
)
195 for (int i
= filenames
.size(); --i
>= 0;)
197 const File
f (filenames
[i
]);
199 if (f
.hasFileExtension (".cpp"))
206 void MainWindow::filesDropped (const StringArray
& filenames
, int mouseX
, int mouseY
)
208 for (int i
= filenames
.size(); --i
>= 0;)
210 const File
f (filenames
[i
]);
212 if (f
.hasFileExtension (".cpp") && openFile (f
))
217 void MainWindow::activeWindowStatusChanged()
219 DocumentWindow::activeWindowStatusChanged();
221 if (isActiveWindow())
222 TestComponent::reloadAll();
225 //==============================================================================
226 const StringArray
MainWindow::getMenuBarNames()
228 const char* const names
[] = { "File", "Edit", "View", 0 };
230 return StringArray (names
);
233 const PopupMenu
MainWindow::getMenuForIndex (int topLevelMenuIndex
,
234 const String
& menuName
)
238 if (topLevelMenuIndex
== 0)
242 for (int i
= 0; i
< ObjectTypes::numDocumentTypes
; ++i
)
243 menu
.addCommandItem (commandManager
, CommandIDs::newDocumentBase
+ i
);
246 menu
.addCommandItem (commandManager
, CommandIDs::open
);
248 PopupMenu recentFiles
;
249 StoredSettings::getInstance()->recentFiles
.createPopupMenuItems (recentFiles
, 100, true, true);
250 menu
.addSubMenu ("Open recent file", recentFiles
);
253 menu
.addCommandItem (commandManager
, CommandIDs::close
);
255 menu
.addCommandItem (commandManager
, CommandIDs::save
);
256 menu
.addCommandItem (commandManager
, CommandIDs::saveAs
);
259 menu
.addCommandItem (commandManager
, StandardApplicationCommandIDs::quit
);
261 else if (topLevelMenuIndex
== 1)
265 menu
.addCommandItem (commandManager
, CommandIDs::undo
);
266 menu
.addCommandItem (commandManager
, CommandIDs::redo
);
269 menu
.addCommandItem (commandManager
, CommandIDs::editCompLayout
);
270 menu
.addCommandItem (commandManager
, CommandIDs::editCompGraphics
);
275 for (i
= 0; i
< ObjectTypes::numComponentTypes
; ++i
)
276 newComps
.addCommandItem (commandManager
, CommandIDs::newComponentBase
+ i
);
278 menu
.addSubMenu ("Add new component", newComps
);
280 PopupMenu newElements
;
281 for (i
= 0; i
< ObjectTypes::numElementTypes
; ++i
)
282 newElements
.addCommandItem (commandManager
, CommandIDs::newElementBase
+ i
);
284 menu
.addSubMenu ("Add new graphic element", newElements
);
287 menu
.addCommandItem (commandManager
, StandardApplicationCommandIDs::cut
);
288 menu
.addCommandItem (commandManager
, StandardApplicationCommandIDs::copy
);
289 menu
.addCommandItem (commandManager
, StandardApplicationCommandIDs::paste
);
290 menu
.addCommandItem (commandManager
, StandardApplicationCommandIDs::del
);
291 menu
.addCommandItem (commandManager
, StandardApplicationCommandIDs::selectAll
);
292 menu
.addCommandItem (commandManager
, StandardApplicationCommandIDs::deselectAll
);
294 menu
.addCommandItem (commandManager
, CommandIDs::toFront
);
295 menu
.addCommandItem (commandManager
, CommandIDs::toBack
);
297 menu
.addCommandItem (commandManager
, CommandIDs::group
);
298 menu
.addCommandItem (commandManager
, CommandIDs::ungroup
);
300 menu
.addCommandItem (commandManager
, CommandIDs::bringBackLostItems
);
302 else if (topLevelMenuIndex
== 2)
306 menu
.addCommandItem (commandManager
, CommandIDs::test
);
308 PopupMenu lookAndFeels
;
309 lookAndFeels
.addItem (201, "Default", true, (typeid (LookAndFeel
) == typeid (LookAndFeel::getDefaultLookAndFeel())) != 0);
310 lookAndFeels
.addItem (200, "Old School", true, (typeid (OldSchoolLookAndFeel
) == typeid (LookAndFeel::getDefaultLookAndFeel())) != 0);
313 menu
.addSubMenu ("Look and Feel", lookAndFeels
);
316 menu
.addCommandItem (commandManager
, CommandIDs::showGrid
);
317 menu
.addCommandItem (commandManager
, CommandIDs::enableSnapToGrid
);
319 const int currentSnapSize
= getActiveDocument() != 0 ? getActiveDocument()->getSnappingGridSize() : 0;
322 for (int i
= 0; i
< numElementsInArray (snapSizes
); ++i
)
323 m
.addItem (300 + i
, String (snapSizes
[i
]) + " pixels", true, snapSizes
[i
] == currentSnapSize
);
325 menu
.addSubMenu ("Grid size", m
, getActiveDocument() != 0);
328 menu
.addCommandItem (commandManager
, CommandIDs::zoomIn
);
329 menu
.addCommandItem (commandManager
, CommandIDs::zoomOut
);
330 menu
.addCommandItem (commandManager
, CommandIDs::zoomNormal
);
334 overlays
.addCommandItem (commandManager
, CommandIDs::compOverlay0
);
335 overlays
.addCommandItem (commandManager
, CommandIDs::compOverlay33
);
336 overlays
.addCommandItem (commandManager
, CommandIDs::compOverlay66
);
337 overlays
.addCommandItem (commandManager
, CommandIDs::compOverlay100
);
338 menu
.addSubMenu ("Component Overlay", overlays
,
339 getActiveDocument() != 0 && getActiveDocument()->getComponentLayout() != 0);
342 menu
.addCommandItem (commandManager
, CommandIDs::useTabbedWindows
);
344 menu
.addCommandItem (commandManager
, CommandIDs::showPrefs
);
350 void MainWindow::menuItemSelected (int menuItemID
,
351 int topLevelMenuIndex
)
353 if (menuItemID
>= 100 && menuItemID
< 200)
355 // open a file from the "recent files" menu
356 JucerDocument
* const newDoc
357 = ObjectTypes::loadDocumentFromFile (StoredSettings::getInstance()->recentFiles
.getFile (menuItemID
- 100),
361 openDocument (newDoc
);
363 else if (menuItemID
== 200)
365 LookAndFeel::setDefaultLookAndFeel (oldLook
);
367 else if (menuItemID
== 201)
369 LookAndFeel::setDefaultLookAndFeel (nullptr);
371 else if (menuItemID
>= 300 && menuItemID
< 400)
373 if (getActiveDocument() != 0)
375 getActiveDocument()->setSnappingGrid (snapSizes
[menuItemID
- 300],
376 getActiveDocument()->isSnapActive (false),
377 getActiveDocument()->isSnapShown());
382 //==============================================================================
383 ApplicationCommandTarget
* MainWindow::getNextCommandTarget()
388 void MainWindow::getAllCommands (Array
<CommandID
>& commands
)
390 for (int i
= 0; i
< ObjectTypes::numDocumentTypes
; ++i
)
391 commands
.add (CommandIDs::newDocumentBase
+ i
);
393 const CommandID ids
[] = { CommandIDs::open
,
394 CommandIDs::showPrefs
,
395 CommandIDs::useTabbedWindows
};
397 commands
.addArray (ids
, numElementsInArray (ids
));
400 void MainWindow::getCommandInfo (const CommandID commandID
, ApplicationCommandInfo
& result
)
402 if (commandID
>= CommandIDs::newDocumentBase
403 && commandID
< CommandIDs::newDocumentBase
+ ObjectTypes::numDocumentTypes
)
405 const int index
= commandID
- CommandIDs::newDocumentBase
;
407 result
.setInfo ("New " + String (ObjectTypes::documentTypeNames
[index
]),
408 "Creates a new " + String (ObjectTypes::documentTypeNames
[index
]),
409 CommandCategories::general
, 0);
414 const int cmd
= ModifierKeys::commandModifier
;
418 case CommandIDs::open
:
419 result
.setInfo ("Open...",
420 "Opens a Jucer .cpp component file for editing.",
421 CommandCategories::general
, 0);
422 result
.defaultKeypresses
.add (KeyPress ('o', cmd
, 0));
425 case CommandIDs::showPrefs
:
426 result
.setInfo ("Preferences...",
427 "Shows the preferences panel.",
428 CommandCategories::general
, 0);
429 result
.defaultKeypresses
.add (KeyPress (',', cmd
, 0));
432 case CommandIDs::useTabbedWindows
:
433 result
.setInfo ("Use tabs to show windows",
434 "Flips between a tabbed component and separate windows",
435 CommandCategories::general
, 0);
436 result
.setTicked (multiDocHolder
->getLayoutMode() == MultiDocumentPanel::MaximisedWindowsWithTabs
);
444 bool MainWindow::isCommandActive (const CommandID commandID
)
449 bool MainWindow::perform (const InvocationInfo
& info
)
451 if (info
.commandID
>= CommandIDs::newDocumentBase
452 && info
.commandID
< CommandIDs::newDocumentBase
+ ObjectTypes::numDocumentTypes
)
454 const int index
= info
.commandID
- CommandIDs::newDocumentBase
;
455 openDocument (ObjectTypes::createNewDocument (index
));
460 switch (info
.commandID
)
462 case CommandIDs::open
:
463 openFile (File::nonexistent
);
466 case CommandIDs::showPrefs
:
470 case CommandIDs::useTabbedWindows
:
471 if (multiDocHolder
->getLayoutMode() == MultiDocumentPanel::MaximisedWindowsWithTabs
)
472 multiDocHolder
->setLayoutMode (MultiDocumentPanel::FloatingWindows
);
474 multiDocHolder
->setLayoutMode (MultiDocumentPanel::MaximisedWindowsWithTabs
);